import React, { Component } from 'react'
import Taro from '@tarojs/taro'
import { View, Image } from '@tarojs/components'

import { concatWithBaseUrl } from '@/utils/ServerUrls'
import { getFullSrcs, showHttpError } from '@/utils/Helper'
import { ImageExts, VideoExts } from '@/utils/FileTypes'
import styles from './index.module.scss'

/**
 * 对外暴露的属性信息
 */
interface propsType {
  onClick?: (item) => void // 点击时，调用方的附加处理
  files: Array<{ url: string; name: string }> | null
}

/**
 * 组件本身需要使用的数据
 */
interface stateType {
  // url 文件地址。如果是包含域名的全路径，将直接使用；如果是相对路径，会拼接为全路径。
  files4Show: Array<{ url: string; name: string }>
}
/**
 * 附件预览组件。（仅预览，不包含上传操作；支持图片和文档。）
 * 以列表的形式呈现附件，点击条目之后对附件进行预览。（图片类直接预览；文档类先下载再预览）
 */
export default class FilesPreview extends Component<propsType, stateType> {
  constructor(props) {
    super(props)
    const { files } = props;
    this.files = files
  }


  state = {
    files4Show: []
  }

  componentDidMount(): void {
    this.getFiles4Show(this.files)
  }

  files: []
  /**
   * 获取用于展示的 files 对象数组
   */
  getFiles4Show = (files) => {
    let tempFiles = []
    // console.debug("files",files, "length", files.length)
    if (files && files.length > 0) {
      // console.debug("length", files.length)
      tempFiles = files.map((item) => {
        let fullUrl = concatWithBaseUrl(item.url)
        return {
          url: fullUrl,
          name: item.name
        }
      })
    }

    // console.debug("files",files)

    // console.debug("files4Show", tempFiles)
    this.setState({
      files4Show: tempFiles
    })
  }

  /**
   * 条目被点击了
   */
  onItemClick = (event, item) => {
    // 基于文件后缀名区分文件类型。
    const lastInfoOfDot = item.url.lastIndexOf('.')
    if (lastInfoOfDot == -1) {
      Taro.showToast({ title: '文件格式有误', icon: 'none' })
      return
    }
    const suffix = item.url.slice(lastInfoOfDot + 1)

    // /** wx.openDocument 中支持的文档格式如下 */
    // const docTypes = ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'pdf']
    // /**
    //  * wx.previewImage 中并没有明确说明支持哪些格式。
    //  * 但如果传入了错误的格式也不会报错——Option 中的 success、fail、comlete 并没有返回错误信息。
    //  * 所以，此处将测试过的图片格式做一个白名单。
    //  */
    // const imgTypes = ['png', 'jpg', 'jpeg', 'bmp', 'webp', 'gif']

    // 除文档类型外，其他一律按照图片资源处理
    // if (docTypes.includes(suffix)) {
    if (ImageExts.includes(suffix)) {
      this.previewImage(event, item.url)
    } else if (VideoExts.includes(suffix)) {
      this.saveVideo(event, item.name, item.url)
    } else {
      this.downloadAndPreivewiDocFile(event, item.name, item.url)
    }
    // } else if (imgTypes.includes(suffix)) {
    //   this.previewImage(event, item.url)
    // } else {
    //   // TODO不支持的文件格式，提示用户下载并使用手机中的其他软件打开。——不行！官方不支持！
    //   // this.download2TargetDir(item.url, item.name)
    //   Taro.showToast({ title: '不支持的格式', icon: 'error' })
    // }
  }

  /**
   * 将文件下载到指定目录中
   * 注意：最终的目录也是在小程序沙盒中。并不能实现向原生App一样直接下载到设备，然后用户可以从文件管理器中查看的效果。——微信目前没有开放相关API
   * @param fileUrl 文件的完整 url
   * @param fi了Name 文件名称
   * @param targetDir 期望的下载目录Uri 。如 shizhong/yezhu
   */
  download2TargetDir = (fileUrl, fileName, targetDir = 'shizhong/yezhu') => {
    let targetUri = `${Taro.env.USER_DATA_PATH}/${targetDir}`

    const fs = Taro.getFileSystemManager()
    var isExist = false //目录是否存在
    try {
      // 判断目录/文件是否存在
      fs.accessSync(targetUri)
      isExist = true
    } catch (e) {
      console.error('判断目录是否存在：', e)
    }
    if (!isExist) {
      try {
        // 创建目录
        fs.mkdirSync(targetUri, true)
      } catch (e) {
        console.error('创建目录失败：', e)
        Taro.showToast({ title: '保存失败', icon: 'error' })
        return
      }
    }

    Taro.downloadFile({
      url: fileUrl,
      filePath: targetUri + '/' + fileName,
      fail: (re) => {
        console.log('下载失败：', re.errMsg)
        Taro.showToast({ title: '下载失败', icon: 'error' })
      },
      success: (re) => {
        console.log('下载成功', re)
        Taro.showToast({ title: '下载成功', icon: 'success' })
      }
    })
  }

  /**
   * 预览图片,预览成功后长按可以弹出操作菜单
   */
  previewImage = async (event, url) => {
    event.stopPropagation()
    Taro.previewImage({
      current: url, // 当前显示图片的http链接
      urls: [url], // 需要预览的图片http链接列表
      showmenu: true, // 展示操作菜单（true和false没看出有啥区别啊）
      fail: (res) => {
        console.log('图片预览失败:', res.errMsg)
        Taro.showToast({ title: '预览失败', icon: 'error' })
      }
    })
  }

  /**
   * 预览视频
   */
  saveVideo = async (event, name, url) => {
    event.stopPropagation()
    Taro.showLoading({ title: '加载中...' })
    // 下载文件到沙盒
    Taro.downloadFile({
      url: url,
      filePath: `${Taro.env.USER_DATA_PATH}/${name}`,
      success: (res) => {
        if (!res || res.statusCode !== 200) {
          showHttpError('预览失败')
          return
        }
        Taro.saveVideoToPhotosAlbum({
          filePath: res.filePath || res.tempFilePath,
          fail: (result) => {
            Taro.showToast({ title: `打开失败文件失`, icon: 'none' })
          }
        })
      },
      complete: (result) => {
        Taro.hideLoading()
      }

    })
  }


  /**
   * 先将文档下载到沙盒中，然后基于沙盒中的临时目录调起预览。
   * 单文件最大上限 50M
   */
  downloadAndPreivewiDocFile = (e, name, url) => {
    e.stopPropagation()
    Taro.showLoading({ title: '加载中...' })
    // 下载文件到沙盒
    Taro.downloadFile({
      url: url,
      filePath: `${Taro.env.USER_DATA_PATH}/${name}`,
      success: (res) => {
        if (!res || res.statusCode !== 200) {
          showHttpError('预览失败')
          return
        }

        // 预览文件
        Taro.openDocument({
          filePath: res.filePath || res.tempFilePath,
          showMenu: true, // 展示右上角的操作菜单，可以保存到本地
          fail: (result) => {
            console.warn('打开文档失败: %s', result.errMsg)
            Taro.showToast({ title: `打开文件失败`, icon: 'none' })
          }
        })
      },
      fail: () => {
        Taro.hideLoading()
        Taro.showToast({ title: '预览失败', icon: 'none' })
      },
      complete: () => {
        Taro.hideLoading()
      }
    })
  }

  /**
   * 获取条目视图
   */
  getItemView = (item, index) => {
    return (
      <View className={styles.itemContainer} key={index} onClick={(event) => this.onItemClick(event, item)}>
        <View className={styles.item}>
          <Image className={styles.icon} src={getFullSrcs('icon/attachment.png')} />

          <View className={styles.title}>
            <text> {item?.name}</text>
          </View>
        </View>
      </View>
    )
  }

  render() {
    const { files4Show } = this.state
    return (
      <>
        {Array.isArray(files4Show) && files4Show.length > 0 && (
          <View className={styles.viewParent}>
            {/* 在这里放置你的实际内容或者遍历files4Show数组进行渲染 */}
            {files4Show.map((item, index) => this.getItemView(item, index))}
          </View>
        )}
      </>
    )
  }
}
